package com.zenchn.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zenchn.annotation.OperLog;
import com.zenchn.entity.HttpDataResult;
import com.zenchn.entity.RegionDO;
import com.zenchn.entity.RegionVO;
import com.zenchn.enums.OperLogActionEnum;
import com.zenchn.enums.SessionAttributeEnum;
import com.zenchn.exception.CheckException;
import com.zenchn.model.*;
import com.zenchn.service.*;
import com.zenchn.utils.CommonUtils;
import io.swagger.annotations.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 区域管理控制器
 *
 * @author panbingqi
 * @date 2021-06-04 17:34
 */
@RestController
@RequestMapping(value = "region")
@Api(value = "区域管理模块相关接口", tags = "系统管理-区域管理")
@RequiresPermissions("region:manage:setting")
public class RegionController {
    private final String MODULE = "系统管理>区域管理";

    @Resource
    private RegionService regionService;

    @Resource
    private RegionDetailService regionDetailService;

    @Resource
    private AreasService areasService;


    /**
     * 分页获取区域信息列表
     *
     * @param keyword
     * @param page
     * @param pageSize
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "分页获取区域信息列表")
    @ApiOperation(value = "分页获取区域信息列表", notes = "分页获取区域信息列表")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "keyword", value = "关键字"),
            @ApiImplicitParam(dataType = "Integer", name = "page", value = "当前第page页"),
            @ApiImplicitParam(dataType = "Integer", name = "pageSize", value = "每页pageSize数量")
    })
    @GetMapping(value = "/list")
    @RequiresPermissions("region:manage:setting")
    public ResponseEntity<HttpDataResult<PageInfo>> list(
            @RequestParam(required = false, value = "keyword") String keyword,
            @RequestParam(required = false, value = "page", defaultValue = "1") Integer page,
            @RequestParam(required = false, value = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        HttpDataResult<PageInfo> result = new HttpDataResult<>(request.getRequestURI());

        TMiRegionExample regionExample = new TMiRegionExample();
        if (keyword != null && !keyword.isEmpty()) {
            regionExample.createCriteria().andRegionNameLike("%" + keyword + "%");
        }

        PageHelper.startPage(page, pageSize);
        PageInfo pageInfo = new PageInfo(regionService.selectByExample(regionExample));

        List<TMiRegion> regionList = pageInfo.getList();
        List<RegionVO> regionVOList = new ArrayList<>();
        for (TMiRegion region : regionList) {
            RegionVO regionVO = new RegionVO();
            BeanUtils.copyProperties(region, regionVO);
            //设置所属省份名称
            TMiRegionDetailExample regionDetailExample = new TMiRegionDetailExample();
            regionDetailExample.createCriteria().andRegionIdEqualTo(region.getRegionId());

            List<String> areasCodeList = regionDetailService.selectByExample(regionDetailExample).stream().map(TMiRegionDetail::getAreasCode).collect(Collectors.toList());
            if (areasCodeList != null && !areasCodeList.isEmpty()) {
                TSysAreasExample areasExample = new TSysAreasExample();
                areasExample.createCriteria().andCodeIn(areasCodeList).andIsEnableEqualTo(true);

                List<TSysAreas> areasList = areasService.selectByExample(areasExample);
                if (areasList != null && !areasList.isEmpty()) {
                    regionVO.setAreasCodeNames(areasList.stream().map(TSysAreas::getName).collect(Collectors.joining(",")));
                }
            }
            regionVOList.add(regionVO);
        }


        pageInfo.setList(regionVOList);

        result.setData(pageInfo);

        result.setMessage("获取区域信息列表成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /**
     * 新增区域信息保存提交
     *
     * @param regionDO
     * @param bindingResult
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.INSERT, detail = "新增区域信息保存提交")
    @ApiOperation(value = "新增区域信息保存提交", notes = "新增区域信息保存提交")
    @ApiParam(type = "RegionDO", name = "regionDO", value = "区域信息新增映射对象", required = true)
    @PostMapping(value = "/addSubmit")
    @RequiresPermissions("region:manage:setting:add")
    public ResponseEntity<HttpDataResult<String>> addSubmit(
            @RequestBody @Validated RegionDO regionDO, BindingResult bindingResult,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        if (bindingResult.hasErrors()) {
            throw new CheckException(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }

        if (!regionService.verifyRegionName(null, regionDO.getRegionName())) {
            throw new CheckException(regionDO.getRegionName() + "区域名称已存在，不要重复输入哦！");
        }

        HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

        final TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());

        //新增区域信息
        TMiRegion region = new TMiRegion();
        BeanUtils.copyProperties(regionDO, region);
        String regionId = CommonUtils.randomUUID();
        LocalDateTime dateTime = LocalDateTime.now();
        region.setRegionId(regionId);
        region.setCreateTime(dateTime);
        region.setCreator(currAccount.getAccountId());

        regionService.insert(region);

        //新增区域详情信息
        List<String> areasCodeList = regionDO.getAreasCodeList();
        if (areasCodeList != null && !areasCodeList.isEmpty()) {
            for (String areasCode : areasCodeList) {
                TMiRegionDetail regionDetail = new TMiRegionDetail();
                String id = CommonUtils.randomUUID();
                regionDetail.setId(id);
                regionDetail.setRegionId(regionId);
                regionDetail.setAreasCode(areasCode);
                regionDetail.setCreator(currAccount.getAccountId());
                regionDetail.setCreateTime(dateTime);

                regionDetailService.insert(regionDetail);
            }
        }

        result.setData(regionId);

        result.setMessage("新增区域信息成功!");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 区域信息详情 （修改页获取数据）
     * @param regionId
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "区域信息详情 （修改页获取数据）")
    @ApiOperation(value = "区域信息详情 （修改页获取数据）", notes = "区域信息详情 （修改页获取数据）")
    @ApiImplicitParam(dataType = "String", name = "regionId", value = "区域ID", required = true)
    @GetMapping(value = "/detail")
    public ResponseEntity<HttpDataResult<Map<String, Object>>> detail(
            @RequestParam(value = "regionId") String regionId,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Map<String, Object>> result = new HttpDataResult<>(request.getRequestURI());
        Map<String, Object> resultData = new HashMap<>(16);

        //获取区域信息
        TMiRegion region = regionService.selectByPrimaryKey(regionId);
        resultData.put("region", region);
        //获取区域详情信息
        TMiRegionDetailExample regionDetailExample = new TMiRegionDetailExample();
        regionDetailExample.createCriteria().andRegionIdEqualTo(regionId);

        List<String> regionDetailIdList = regionDetailService.selectByExample(regionDetailExample).stream().map(TMiRegionDetail::getAreasCode).collect(Collectors.toList());

        resultData.put("regionDetailIdList", regionDetailIdList);

        result.setData(resultData);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /**
     * 修改区域信息保存提交
     *
     * @param regionDO
     * @param bindingResult
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.UPDATE, detail = "修改区域信息保存提交")
    @ApiOperation(value = "修改区域信息保存提交", notes = "修改区域信息保存提交")
    @ApiParam(type = "RegionDO", name = "regionDO", value = "修改区域信息映射对象", required = true)
    @PutMapping(value = "/modifySubmit")
    @RequiresPermissions("region:manage:setting:modify")
    public ResponseEntity<HttpDataResult<String>> modifySubmit(
            @RequestBody @Validated RegionDO regionDO, BindingResult bindingResult,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

        if (bindingResult.hasErrors()) {
            throw new CheckException(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }

        if (!regionService.verifyRegionName(regionDO.getRegionId(), regionDO.getRegionName())) {
            throw new CheckException(regionDO.getRegionName() + "区域名称已存在，无法修改保存！");
        }
        TMiRegion region = regionService.selectByPrimaryKey(regionDO.getRegionId());

        if (null == region) {
            throw new CheckException("区域ID无效，请检查！");
        }

        final TSysAccount currAccount = (TSysAccount) request.getSession().getAttribute(SessionAttributeEnum.CURRENT_ACCOUNT_INFO.getKey());

        //维护区域表
        region.setRegionName(regionDO.getRegionName());

        regionService.updateByPrimaryKey(region);
        //维护区域详情表(先删除，后添加)
        TMiRegionDetailExample regionDetailExample = new TMiRegionDetailExample();
        regionDetailExample.createCriteria().andRegionIdEqualTo(regionDO.getRegionId());

        regionDetailService.deleteByExample(regionDetailExample);
        List<String> areasCodeList = regionDO.getAreasCodeList();
        if (areasCodeList != null && !areasCodeList.isEmpty()) {
            for (String areasCode : areasCodeList) {
                TMiRegionDetail regionDetail = new TMiRegionDetail();
                String id = CommonUtils.randomUUID();
                regionDetail.setId(id);
                regionDetail.setRegionId(regionDO.getRegionId());
                regionDetail.setAreasCode(areasCode);
                regionDetail.setCreator(currAccount.getAccountId());
                regionDetail.setCreateTime(LocalDateTime.now());

                regionDetailService.insert(regionDetail);
            }
        }

        result.setData(region.getRegionId());

        result.setMessage("修改区域信息成功!");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /***
     * 验证区域名称唯一性
     * @param regionId
     * @param regionName
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.CHECK, detail = "验证区域名称唯一性", isSaveRequestData = true)
    @ApiOperation(value = "验证区域名称唯一性", notes = "验证区域名称唯一性")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "regionId", value = "区域ID", required = false),
            @ApiImplicitParam(dataType = "String", name = "regionName", value = "区域名称", required = true)
    })
    @GetMapping(value = "/verifyRegionName")
    public ResponseEntity<HttpDataResult<Boolean>> verifyRegionName(
            @RequestParam(required = false, value = "regionId") String regionId,
            @RequestParam(value = "regionName") String regionName,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Boolean> result = new HttpDataResult<>(request.getRequestURI());

        result.setData(regionService.verifyRegionName(regionId, regionName));

        result.setMessage("验证区域名称唯一性成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }

    /***
     *  删除区域信息
     * @param regionIds
     * @param request
     * @param response
     * @return
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.DELETE, detail = "删除区域信息")
    @ApiOperation(value = "删除区域信息", notes = "删除区域信息")
    @ApiImplicitParam(dataType = "String[]", allowMultiple = true, name = "regionIds", value = "区域ID数组 示例[1,2,3,4]", required = true)
    @DeleteMapping(value = "/delete/{regionIds}")
    @RequiresPermissions("region:manage:setting:delete")
    public ResponseEntity<HttpDataResult<Boolean>> delete(
            @PathVariable("regionIds") String[] regionIds,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Boolean> result = new HttpDataResult<>(request.getRequestURI());


        if (null == regionIds || regionIds.length == 0) {
            throw new CheckException("需要删除的区域ID异常，删除操作失败！");
        }

        //删除区域信息
        List<String> regionIdList = new ArrayList<>(Arrays.asList(regionIds));
        TMiRegionExample regionExample = new TMiRegionExample();
        regionExample.createCriteria().andRegionIdIn(regionIdList);

        regionService.deleteByExample(regionExample);

        //删除区域详情信息
        TMiRegionDetailExample regionDetailExample = new TMiRegionDetailExample();
        regionDetailExample.createCriteria().andRegionIdIn(regionIdList);

        regionDetailService.deleteByExample(regionDetailExample);

        result.setData(true);
        result.setMessage("删除成功！");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }
}

